//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   FissionSource.hh
 * \author Jeremy Roberts
 * \date   Aug 20, 2011
 * \brief  FissionSource class definition.
 * \note   Copyright (C) 2011 Jeremy Roberts. 
 */
//---------------------------------------------------------------------------//
// $Rev:: 126                                           $:Rev of last commit
// $Author:: j.alyn.roberts@gmail.com                   $:Author of last commit
// $Date:: 2011-09-04 23:13:48 +0000 (Sun, 04 Sep 2011) $:Date of last commit
//---------------------------------------------------------------------------//


#ifndef FISSIONSOURCE_HH_
#define FISSIONSOURCE_HH_

#include "angle/AngleTraits.hh"

#include "material/Materials.hh"

#include "tran/Definitions.hh"
#include "tran/State.hh"
#include "tran/CartMesh.hh"
#include "tran/Moments_Field.hh"

#include "../utilities/SP.hh"

namespace slabtran
{

//===========================================================================//
/*!
 * \class FissionSource
 * \brief Defines a fission source for multiplication problems.
 *
 * The FissionSource class can be used in both eigenvalue problems and
 * fixed source problems with multiplication.  In the latter case, a value
 * of \f$k_{e\!f\!f}\f$ can be given, the inverse of which becomes a
 * multiplier on the source.
 *
 * The fission source is isotropic in angle, meaning it has components
 * corresponding only to moment terms with \f$l=m=0\f$.
 *
 * \tparam  Equations   Equation set.
 * \tparam  D           Dimension.
 *
 */
template <class Equations, class D>
class FissionSource
{

public:

  /// Typedefs
  //\{
  //
  typedef typename util::SP<FissionSource<Equations, D> >   SP_fissionsource;
  //
  typedef typename State<Equations, D>::SP_state            SP_state;
  typedef typename Base_Mesh::SP_mesh                       SP_mesh;
  typedef Materials::SP_materials                           SP_materials;
  //
  typedef Moments_Field<Equations, D>                       Moments_Field_t;
  typedef Cell_Field<double>                                FissionDensityField;
  typedef Cell_Field<double>                                FissionSourceField;
  //\}

  /*!
   *  \brief Constructor.
   *
   * \param state           The state.
   * \param mesh            The mesh.
   * \param materials       The material library.
   *
   */
  FissionSource(SP_state state, SP_mesh mesh, SP_materials materials);


  /*!
   *  \brief Build the fission source density.
   *
   *  This is defined mathematically as
   *  \f[
   *     d_f = \sum_{g'=1} \nu_{gg'} \Sigma_{fg'} \phi_{g'} \, .
   *  \f]
   *
   *  This function is called at the beginning of an outer iteration.  The
   *  eigenvalue is set at this time for proper scaling of the fission
   *  source, as constructed via \ref build_fission_source.
   *
   *  \param    keff    Most recent value for eigenvalue.
   */
  void build_fission_density(double keff);

  /*!
   *  \brief Build the fission source for a group.
   *
   *  This is defined as
   *  \f[
   *     q_f = \frac{\chi_g}{4\pi}
   *           \sum_{g'=1} \nu_{gg'} \Sigma_{fg'} \phi_{g'} \, ,
   *  \f]
   *  or with a normalization of two for 1-d problems.
   *
   *  This builds the isotropic source for each spatial unknown (cells and
   *  nodes) with proper normalization.  It's size is the same as zeroth
   *  order (i.e. \f$l=0\f$) flux moments vector for a group.
   *
   *  This source  accessed via \ref q_f.
   *
   *  \param    g   Group of source to construct.
   */
  void build_fission_source(int g);

  /// \name Accessors
  //\{

  /// Get const access to fission density.
  const FissionDensityField& get_fission_density() const
  {
    return d_density;
  }

  /// Get const access to fission group source.
  const FissionSourceField& get_fission_source() const
  {
    return d_source;
  }

  /*!
   *  \brief Get fission source for a cell and group in particles/cm^3-ster.
   *
   *  \param    cell    Spatial cell cardinal index.
   *  \param    n       Spatial cell unknown (node).
   *  \param    g       Source group.
   *  \return           Fission source in cell and group.
   */
  double q_f(int cell, int n, int g) const
  {
    Require(g == d_group);    // Need to ask for the group we've set.
    return d_source(cell, n);
  }

  /// Return the factor.
  double factor() const
  {
    return d_factor;
  }

  /// Return the state.
  SP_state state() const
  {
    return d_state;
  }

  /// Return the mesh.
  SP_mesh mesh() const
  {
    return d_mesh;
  }

  // \}


private:

  //---------------------------------------------------------------------------
  /// \name  Fission source data
  //\{

  /// Fission source density.
  FissionDensityField d_density;

  /// Fission source for one group.
  FissionSourceField d_source;

  /// Fission density has been built.
  bool d_density_built;

  /// Group for which source is built.
  int d_group;

  /// Normalization factor for the source (i.e. 1/(4*pi*keff))
  double d_factor;

  //\}

  //---------------------------------------------------------------------------
  /// \name Smart pointers to other objects.
  //\{

  /// State.
  SP_state d_state;

  /// Mesh.
  SP_mesh d_mesh;

  /// Materials.
  SP_materials d_materials;

  //\}

};

} // end namespace slabtran

//---------------------------------------------------------------------------//
// INLINE FUNCTIONS
//---------------------------------------------------------------------------//

//#include "tran/FissionSource.i.hh"

#endif /* FISSIONSOURCE_HH_ */

//---------------------------------------------------------------------------//
//              end of FissionSource.hh
//---------------------------------------------------------------------------//
